﻿
Imports std

Partial Public Class distributor
    Protected Class distribute_internal
        Public Shared Sub assert_input(Of T As ijob) _
                                      (ByVal inputJob As T,
                                       ByVal targetJobs As vector(Of pair(Of UInt32, ijob)))
            assert(Not inputJob Is Nothing)
            assert(Not targetJobs Is Nothing)
            assert(targetJobs.empty())
        End Sub
    End Class

    Protected Delegate Function select_d(Of T As ijob)(ByVal i As T) As UInt32
    Protected Shared Function select_distribute(Of T As ijob) _
                                               (ByVal inputJob As T,
                                                ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                                ByVal [select] As select_d(Of T)) As Boolean
        assert(Not [select] Is Nothing)
        distribute_internal.assert_input(inputJob, targetJobs)
        Return targetJobs.push_back(make_pair([select](inputJob), inputJob))
    End Function

    Protected Shared Function select_distribute(Of T As ijob) _
                                               (ByVal inputJob As T,
                                                ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                                ByRef waitall As Boolean,
                                                ByVal [select] As select_d(Of T)) As Boolean
        waitall = True
        Return select_distribute(inputJob, targetJobs, [select])
    End Function

    Protected Function passthrough_distribute(ByVal inputJob As ijob,
                                              ByVal targetJobs As vector(Of pair(Of UInt32, ijob))) As Boolean
        assert(targetQueues.size() = 1)
        Return select_distribute(inputJob, targetJobs,
                                 Function(i As ijob) As UInt32
                                     Return 0
                                 End Function)
    End Function

    Protected Function passthrough_distribute(ByVal inputJob As ijob,
                                              ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                              ByRef waitall As Boolean) As Boolean
        waitall = True
        Return passthrough_distribute(inputJob, targetJobs)
    End Function

    Protected Function hash_distribute(ByVal inputJob As ijob,
                                       ByVal targetJobs As vector(Of pair(Of UInt32, ijob))) As Boolean
        Return select_distribute(inputJob, targetJobs,
                                 Function(i As ijob) As UInt32
                                     Return hashcode(i)
                                 End Function)
    End Function

    Protected Function hash_distribute(ByVal inputJob As ijob,
                                       ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                       ByRef waitall As Boolean) As Boolean
        waitall = True
        Return hash_distribute(inputJob, targetJobs)
    End Function

    Protected Function random_distribute(ByVal inputJob As ijob,
                                         ByVal targetJobs As vector(Of pair(Of UInt32, ijob))) As Boolean
        Return select_distribute(inputJob, targetJobs,
                                 Function(i As ijob) As UInt32
                                     Return rnd_int(0, targetQueues().size())
                                 End Function)
    End Function

    Protected Function random_distribute(ByVal inputJob As ijob,
                                         ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                         ByRef waitall As Boolean) As Boolean
        waitall = True
        Return random_distribute(inputJob, targetJobs)
    End Function

    Protected Function random_distribute(ByVal inputJob As ijob,
                                         ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                         ByVal start As UInt32,
                                         ByVal max_range As UInt32) As Boolean
        assert(start >= 0 AndAlso start < targetQueues.size())
        For i As Int32 = 0 To rnd_int(0, max_range) - 1
            start = nextQueueIndex(start)
        Next
        Return select_distribute(inputJob, targetJobs,
                                 Function(i As ijob) As UInt32
                                     Return start
                                 End Function)
    End Function

    Protected Function random_distribute(ByVal inputJob As ijob,
                                         ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                         ByRef waitall As Boolean,
                                         ByVal start As UInt32,
                                         ByVal max_range As UInt32) As Boolean
        waitall = True
        Return random_distribute(inputJob, targetJobs, start, max_range)
    End Function

    Protected Function hash_random_distribute(ByVal inputJob As ijob,
                                              ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                              ByVal max_range As UInt32) As Boolean
        Return random_distribute(inputJob, targetJobs, hashcode(inputJob), max_range)
    End Function

    Protected Function hash_random_distribute(ByVal inputJob As ijob,
                                              ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                              ByRef waitall As Boolean,
                                              ByVal max_range As UInt32) As Boolean
        waitall = True
        Return hash_random_distribute(inputJob, targetJobs, max_range)
    End Function

    Protected Function redundance_hash_random_distribute(
                                            ByVal inputJob As ijob,
                                            ByVal targetJobs As vector(Of pair(Of UInt32, ijob))) As Boolean
        assert(Not redundance_count Is Nothing)
        Return hash_random_distribute(inputJob, targetJobs, redundance_count())
    End Function

    Protected Function redundance_hash_random_distribute(
                                            ByVal inputJob As ijob,
                                            ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                            ByRef waitall As Boolean) As Boolean
        waitall = True
        Return redundance_hash_random_distribute(inputJob, targetJobs)
    End Function

    Protected Function spread_distribute(ByVal inputJob As ijob,
                                         ByVal targetJobs As vector(Of pair(Of UInt32, ijob))) As Boolean
        distribute_internal.assert_input(inputJob, targetJobs)
        For i As UInt32 = 0 To targetQueues().size() - 1
            targetJobs.push_back(make_pair(i, inputJob))
        Next
        Return True
    End Function

    Protected Function spread_distribute(ByVal inputJob As ijob,
                                         ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                         ByRef waitall As Boolean) As Boolean
        waitall = True
        Return spread_distribute(inputJob, targetJobs)
    End Function

    Protected Function hash_redundance_distribute(ByVal inputJob As ijob,
                                                  ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                                  ByVal redundance_count As UInt32) As Boolean
        distribute_internal.assert_input(inputJob, targetJobs)
        Return foreach_redundance_queue(inputJob,
                                        Function(ByRef index As UInt32) As Boolean
                                            Return targetJobs.push_back(make_pair(index, inputJob))
                                        End Function,
                                        redundance_count)
    End Function

    Protected Function hash_redundance_distribute(ByVal inputJob As ijob,
                                                  ByVal targetJobs As vector(Of pair(Of UInt32, ijob))) As Boolean
        assert(Not redundance_count Is Nothing)
        Return hash_redundance_distribute(inputJob, targetJobs, redundance_count())
    End Function

    Protected Function hash_redundance_distribute(ByVal inputJob As ijob,
                                                  ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                                  ByRef waitall As Boolean,
                                                  ByVal redundance_count As UInt32) As Boolean
        waitall = True
        Return hash_redundance_distribute(inputJob, targetJobs, redundance_count)
    End Function

    Protected Function hash_redundance_distribute(ByVal inputJob As ijob,
                                                  ByVal targetJobs As vector(Of pair(Of UInt32, ijob)),
                                                  ByRef waitall As Boolean) As Boolean
        assert(Not redundance_count Is Nothing)
        Return hash_redundance_distribute(inputJob, targetJobs, waitall, redundance_count())
    End Function
End Class
